AWS KMSで公開鍵暗号してみた
AWS Key Management Service(KMS)は2019年末に非対称鍵にサポートするようになりました。 非対称鍵は
- データの暗号・復号
- デジタル署名の署名・検証
などに利用できます。
今回は、KMSの非対称鍵を利用してデータを暗号・復号(公開鍵暗号)する方法を紹介します。
後者のデジタル署名については、以下のブログを参照ください。
- [アップデート] KMS で非対称キーペア(公開鍵暗号方式)が利用できるようになったのでデジタル署名を試してみました! | Developers.IO
- AWS KMS の新機能 公開鍵暗号によるデジタル署名 | Amazon Web Services ブログ
対称鍵と非対称鍵の暗号化の使い分け
AWS KMSでは従来から対称鍵を利用した暗号・復号にも対応していました。 違いを確認します。
対称鍵暗号は以下の流れで暗号・復号します。
- [暗号データの受信者]対称鍵を作成
- [暗号データの作成者]対称鍵を使ってデータを暗号化
- [暗号データの作成者]暗号文を受信者に送付
- [暗号データの受信者]暗号文を対称鍵で復号
対称鍵のポイントは、暗号と復号で同じ鍵を利用することです。
一方で、非対称鍵を利用する公開鍵暗号は以下の流れで暗号・復号します。
- [暗号データの受信者]公開鍵のキーペアを作成
- [暗号データの受信者]暗号データの作成者に公開鍵を送付
- [暗号データの作成者]公開鍵を使ってデータを暗号化
- [暗号データの作成者]暗号文を受信者に送付
- [暗号データの受信者]暗号文を秘密鍵で復号
公開鍵暗号のポイントは
- 暗号と復号で異なる鍵を利用
- 暗号に利用する公開鍵はだれでもアクセス可能
- 復号に利用する秘密鍵は受信者だけがアクセス可能
ということです。
AWS KMSに置き換えてみます。
従来の対称鍵暗号では、暗号・復号時にKMSの対称鍵へのアクセス権限が必要でした。
公開鍵暗号では、復号時にはKMSの秘密鍵へのアクセスが必要ですが、暗号時にはキー生成後にダウンロード可能な公開鍵だけが必要です。AWSへのアクセスは不要です。
したがって、AWS外で発生するデータを誰でもアクセスできる公開鍵で暗号化し、AWS内でKMS APIから秘密鍵を使って復号化する、といったことが可能になります。
RSA_OAEPで暗号化する
任意のデータを送信すると、それを暗号文とみなして復号化し、返信してくれるサービスを攻撃者が利用できることを仮定した攻撃を「選択暗号文攻撃(Chosen-ciphertext Attack/CCA)」と呼びます。
生RSA暗号はCCA攻撃に安全でないことが知られています。
そこで、攻撃に対して安全になるように改良されたのが RSA_OAEP です。 RSA_OAEP では平文をOAEPパディング後、 RSA暗号します。
AWS KMSの公開鍵暗号はこの RSA_OAEP アルゴリズム、具体的には
- RSAES_OAEP_SHA_1
- RSAES_OAEP_SHA_256
のみに対応しています。
生RSA には対応していない点にご注意ください。
Q: どのような種類の非対称暗号化アルゴリズムがサポートされていますか?
AWS KMS では、RSAES_OAEP_SHA_1 と RSAES_OAEP_SHA_256 の暗号化アルゴリズムおよび RSA 2048、RSA 3072、RSA 4096 のキータイプをサポートしています。暗号化アルゴリズムは、楕円曲線キータイプ (ECC NIST P-256、ECC NIST P-384、ECC NIST-521、ECC SECG P-256k1) と一緒に使用することはできません。
AWS KMSの公開鍵で暗号化してみる
AWS KMSで非対称鍵を作成し、公開鍵暗号で暗号・復号してみます。
公開鍵暗号用の鍵の作成
公開鍵暗号用の鍵を作成するには、「キーのタイプ」に「非対称鍵」を選択し、「キーの使用」に「暗号化および復号化」を選択します。
上述の通り、「キーの仕様」で指定するキーのビット長によって、暗号化可能なデータサイズが異なります。
データの暗号化
公開鍵暗号では、公開鍵で暗号化します。
鍵の詳細画面の「パブリックキー」タブから公開鍵をダウンロードします。
なお、このフローに従い作成される鍵の秘密鍵はカスタマーマスターキー(CMK)です。 KMSサービスの外側に出ることはありません。
次に、ダウンロードした公開鍵を利用し、RSA_OAEP方式で暗号化します。
openssl
コマンドを利用すると、暗号化処理を簡単に行えます。
RSAES_OAEP_SHA_256
アルゴリズムで暗号化してみます。
$ openssl version OpenSSL 1.0.2t 10 Sep 2019 $ echo hello world! > plaintext $ openssl pkeyutl -in plaintext \ -encrypt -pubin \ -inkey Publickey-xxx-xxx-xxx.pem \ -pkeyopt rsa_padding_mode:oaep \ -pkeyopt rsa_oaep_md:sha256 \ -pkeyopt rsa_mgf1_md:sha256 > ciphertext
重要なオプションを解説します。
-in
: 暗号化するファイル-inkey
: 暗号化に利用する公開鍵ファイル-pkeyopt
: RSA_OAEP_SHA_256 アルゴリズム用のオプション
データの復号化
復号には kms::decrypt
API を利用します。
重要なオプションを解説します。
--key-id
: 暗号時に利用した鍵--ciphertext-blob
: 暗号文--encryption-algorithm
: 暗号アルゴリズム
$ aws kms decrypt \ --key-id alias/rsa \ --ciphertext-blob fileb://ciphertext \ --encryption-algorithm RSAES_OAEP_SHA_256 { "KeyId": "arn:aws:kms:eu-central-1:1234:key/aa-bb-cc-de", "Plaintext": "aGVsbG8gd29ybGQhCg==", "EncryptionAlgorithm": "RSAES_OAEP_SHA_256" }
復号化された平文(レスポンスの Plaintext
)は base64 エンコードされています。
base64 デコードして、メッセージを確認します。
$ echo aGVsbG8gd29ybGQhCg== | base64 -D hello world!
期待通り復号化されています。
AWS API で暗号化
openssl
コマンドを使わずに、AWS REST APIのkms::encrypt
で暗号化することも出来ます。
$ aws kms encrypt \ --key-id alias/rsa \ --encryption-algorithm RSAES_OAEP_SHA_256 \ --plaintext fileb://plaintext { "CiphertextBlob": "...", "KeyId": "arn:aws:kms:eu-central-1:1234:key/aa-bb-cc-de", "EncryptionAlgorithm": "RSAES_OAEP_SHA_256" }
対称鍵の時は、鍵(--key-id
)を指定するだけで暗号化されました。
非対称鍵の時は、OAEP用のアルゴリズム(--encryption-algorithm
)も指定します。
暗号文はレスポンスの CiphertextBlob
にあり、base64 エンコードされています。
デコードした上でファイル保存します。
$ aws kms encrypt \ --key-id alias/rsa \ --encryption-algorithm RSAES_OAEP_SHA_256 \ --plaintext fileb://plaintext \ --output text \ --query CiphertextBlob | base64 -D > ciphertext_cli
この暗号文を kms::decrypt
で復号化してみます。
$ aws kms decrypt \ --key-id alias/rsa \ --ciphertext-blob fileb://ciphertext_cli \ --encryption-algorithm RSAES_OAEP_SHA_256 \ --output text \ --query Plaintext | base64 -D hello world!
期待通り復号化されています。
制限
暗号・復号に利用できる非対称鍵
AWS KMSが提供する非対称鍵は
- RSA系
- 楕円曲線系
の2種類があります。
この内、暗号・復号に対応しているのはRSA系のみです。
暗号化できるデータサイズ
RSA鍵と暗号アルゴリズムによって、暗号化できる平文の最大データサイズが異なります。
キー仕様 | RSAES_OAEP_SHA_1 | RSAES_OAEP_SHA_256 |
---|---|---|
RSA_2048 | 214 | 190 |
RSA_3072 | 342 | 318 |
RSA_4096 | 470 | 446 |
※単位はバイト
参考までに、対称鍵が暗号化できる最大長は4096バイトです。
公開鍵暗号は遅く、大きいデータを暗号化できない
公開鍵暗号は処理に時間がかかり、暗号化できるデータサイズも小さいという制約があります。
そのため、例えば エンベロープ暗号を採用し、AES のような高速な対称暗号でデータを暗号後、AESで利用したデータキーを公開鍵で暗号化すると、様々なサイズのデータを暗号化出来ます。
最後に
AWS KMSは非対称暗号の公開鍵暗号に対応しています。 公開鍵暗号では、誰でもアクセス可能な公開鍵が暗号に用いられ、AWS KMS利用者だけがアクセス可能な秘密鍵が復号に用いられます。 そのため、AWS外で発生するデータを公開鍵で暗号化し、AWS内でAWS KMS管理された秘密鍵で復号化するといった運用が可能です。
暗号化の際には、選択暗号文攻撃に対して安全になるために、RSA OAEPアルゴリズムで暗号化する点にご留意してください。
それでは。